﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace osDinamicMemory
{
	public class Sections
	{
		public int size;
		public int allocation;

		public Sections(int size, int allocation)
		{
			this.size = size;
			this.allocation = allocation;
		}
	}

	public class FackMemory
	{
		public byte[] memory;

		public List<Sections> SectionsIsFull = new List<Sections>();
		public List<Sections> SectionsIsEmpty = new List<Sections>(); 

		public FackMemory(byte[] memory)
		{
			this.memory = memory;
		}
		
		public int MemoryAllocation(int size)
		{
			for (int i = 0; i < memory.Length; i++)
			{
				if (memory[i] == 0)
				{
					int blocksize = 0;
					int j = i;
					for (; j < memory.Length; j++)
					{
						if (memory[j] == 1)
						{
							break;
						}

						blocksize++;

						if (blocksize == size)
						{
							this.Mark(i, j, 1);
							return i;
						}
					}
				}
				else
				{
					continue;
				}
			}

			throw new OutOfMemoryException();
		}

		public void CleanupMemory(int location)
		{
			int size = memory[location];
			while (size != 0)
			{
				memory[location] = 0;
				location++;
				size--;
			}
		}

		public List<Sections> GetFullSections()
		{
			return this.GetSectionFullInfo();
		}

		public List<Sections> GetEmptySections()
		{
			return this.GetSectionEmptyInfo();
		}

		private List<Sections> GetSectionFullInfo()
		{
			var section = new List<Sections>();
			int i = 0;
			while (i < this.memory.Length)
			{
				if (this.memory[i] > 0)
				{
					int size = this.memory[i];
					int allocation;
					if (i == 0)
					{
						allocation = 0;
					}
					else
					{
						allocation = i + 1;
					}
					section.Add(new Sections(size, allocation));
					i = size + i;
					continue;
				}
				else
				{
					i++;
				}
			}

			return section;
		}

		private List<Sections> GetSectionEmptyInfo()
		{
			int i = 0;
			var sectionses = new List<Sections>();
			while (i < this.memory.Length)
			{
				if (this.memory[i] == 0)
				{
					int allocation = i + 1;
					int j = i;
					int size = 1;

					while ((this.memory[j] == 0) && (j != this.memory.Length - 1))
					{
						size++;
						j++;
					}

					i = i + size;
					sectionses.Add(new Sections(size - 1, allocation));
					continue;
				}

				i++;
			}

			return sectionses;
		}

		private void Mark(int i, int j, byte value)
		{
			this.memory[i] = (byte)(j - i + 1);

			for (int board = i + 1; board != j + 1; board++)
			{
				this.memory[board] = value;
			}
		}
	}
}
